/**
 * @author Rudy Kaplan Depena (The University of Texas at Austin)
 */
package com.utaustin.mirankerlab.ultrawrap.compiler.utilities;

import java.util.Set;
import java.util.HashSet;
import com.utaustin.mirankerlab.ultrawrap.compiler.components.Component;
import com.utaustin.mirankerlab.ultrawrap.compiler.exceptions.ComponentNeverEncounteredException;

/** Class that keeps track of bookkeeping to assist in compilation which 
 *  includes keeping track of first components encountered 
 */
public class BookKeeper {
	
	//instance variables
	private Set<Component> firstComponents;//contains and adds first component on sight
	
	
	/**
	 * Default Constructor
	 */
	public BookKeeper(){ firstComponents = new HashSet<Component>();  }
	
	/**
	 * Add component if not already present and component is part of a triple
	 * @param component
	 * @param tripleId
	 */
	public void addComponent(Component component){
		//figure out if component is there
		Component firstComponentEncountered = findComponent(component);
		
		//if there is no component in list already 
		//and component you want to add is found as part of a triple
		if(firstComponentEncountered == null && component.getTripleId() > 0)
			firstComponents.add(component); //then add component to set
	}
	
	/**
	 * If rawStr of component is found within 
	 * first components encountered, then return tripleId.
	 * Else return -1 (which means it is not found)
	 * @param rawStr
	 * @return tripleId
	 */
	public Integer getFirstTripleIdEncountered(Component component){
		
		//acquire first component
		Component firstComponentEncountered = findComponent(component);
		
		//if component found, return it's triple id
		if(firstComponentEncountered != null) return firstComponentEncountered.getTripleId();
		
		//else return -1 for not found
		return -1;
	}
	
	/**
	 * Get kind of first occurrence
	 * @param component
	 * @param mainSelects
	 * @return sql statement
	 */
	public String getFirstKindOfOccurance(Component component, boolean mainSelects) 
	throws ComponentNeverEncounteredException
	{
		//acquire first component
		Component firstComponentEncountered = findComponent(component);
		
		if(firstComponentEncountered == null)
		{
			throw new ComponentNeverEncounteredException(component.toString());
		}
		
		if(mainSelects){
			if(firstComponentEncountered.isSubject()) {return "s";}
			if(firstComponentEncountered.isSubjectKey()) {return "spk";}
			if(firstComponentEncountered.isPredicate()) {return "p";}
			if(firstComponentEncountered.isObject()) {return "o";}
			if(firstComponentEncountered.isObjectKey()) {return "opk";}
		}
		else{
			if(firstComponentEncountered.isSubject() 
			   || firstComponentEncountered.isSubjectKey()){
				return "spk";
			}
			if(firstComponentEncountered.isPredicate()){
				return "p";
			}
			if(firstComponentEncountered.isObject() 
			   || firstComponentEncountered.isObjectKey()){
				return "opk";
			}
		}
		
		
/*		if(firstComponentEncountered.isSubject() && mainSelects == true){
			return "s";
		}
		if(firstComponentEncountered.isSubjectKey() && mainSelects == true){
			return "spk";
		}
		if(firstComponentEncountered.isPredicate()){
			return "p";
		}
		if(firstComponentEncountered.isObject()){
			return "opk";
		}
		if(firstComponentEncountered.isObjectKey()){
			return "opk";
		}*/
		return null;
	}
	
	/**
	 * Update first occurance of component with Subject, Predicate, Object information
	 * @param componentToUpdate
	 * @param String for spo
	 */
	public void updateFirstEncounteredComponent(Component componentToUpdate, String spo){
		for(Component firstComponentEncountered : firstComponents){
			if(firstComponentEncountered.getRawImg().equals(componentToUpdate.getRawImg()) 
				&& firstComponentEncountered.getTripleId() == componentToUpdate.getTripleId()
/*				&& firstComponentEncountered.isSubject() == false
				&& firstComponentEncountered.isSubjectKey() == false
				&& firstComponentEncountered.isPredicate() == false
				&& firstComponentEncountered.isObject() == false
				&& firstComponentEncountered.isObjectKey() == false*/){
				if(spo.equals("subject")){
					firstComponentEncountered.setSubject();
					return;
				}
				else if(spo.equals("subject key")){
					firstComponentEncountered.setSubjectKey();
					return;
				}
				else if(spo.equals("predicate")){
					firstComponentEncountered.setPredicate();
					return;
				}
				else if(spo.equals("object")){
					firstComponentEncountered.setObject();
					return;
				}
				else if(spo.equals("object key")){
					firstComponentEncountered.setObjectKey();
					return;
				}
			}
		}
	}
	
	/**
	 * This is a toString method that returns the string representation of the 
	 * components first encountered in a SPARQL query
	 * @return String of components first encountered
	 */
	public String toString(){
		String result = "";
		for(Component comp : firstComponents)
			result += comp + "; ";
		return result;
	}
	
	/**
	 * Clear the BookKeeper
	 */
	public void emptyBookKeeper(){
		firstComponents.clear();
	}
	
	/**
	 * Find out if component is in map of components. If so, then first component.
	 * Else return false
	 * @param component
	 * @return first component encountered
	 */
	private Component findComponent(Component component){
		for(Component comp : firstComponents){
			if(comp.getRawImg().equals(component.getRawImg()))
				return comp;
		}
		return null;
	}

}
